﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnergyMonitor;
using EnergyAggregator;
using Configuration;
using ApplicationSupport;
using System.Timers;
using Extensions;

namespace envir2plotwatt
{
    public class TheDoc
    {
        private delegate void StringOutput(string outputString);

        private Configuration<ApplicationConfiguration> m_config;

        public PlotWatt Aggregator { get; set; }
        public Envir Monitor { get; set; }
        public ApplicationConfiguration AppConfig { get; set; }
        public PathManager PathManager { get; set; }

        Timer tmUploadData = new Timer();

        public TheDoc()
        {
            PathManager = new PathManager(ApplicationInstallType.SYSTEM);
            Aggregator = new PlotWatt();
            Monitor = new Envir();

            m_config = new Configuration<ApplicationConfiguration>(PathManager.ApplicationDirectory);
            if (!m_config.Load())
            {
                m_config.LoadDefault();
            }
            AppConfig = m_config.ConfigurationItem;

            if (AppConfig.Mappings == null || AppConfig.Mappings.Count == 0)
            {
                AppConfig.Mappings = new MonitorToMeterMappings();
                AppConfig.Mappings.Add(new MonitorToMeter() { Meter = "Monitor1", Monitor = "2345" });
            }

            m_config.Save();

            ConfigureAggregator();
            ConfigureMonitor();
            ConfigureTimers();
        }

        public void SaveConfiguration()
        {
            m_config.Save();
        }

        private void ConfigureTimers()
        {
            // timer for when we will upload to our aggregator if we have data
            tmUploadData.Interval = 10000;
            tmUploadData.Elapsed += UploadDataTick;
            tmUploadData.Start();
        }

        public void SetDisplayOutput(Envir.DisplayString del)
        {
            Monitor.SetDisplay(del);
        }

        private void ConfigureAggregator()
        {
            // configure our data aggregator
            Aggregator.UserName = AppConfig.UserName;
            Aggregator.Password = AppConfig.Password;
        }

        /// <summary>
        /// 
        /// </summary>
        private void ConfigureMonitor()
        {
            // TODO read the comms port from the configuration when available
            // TODO we need to account for com port configuration changing whils running
            // configure our energy monitor and start it monitoring
            Monitor.SetCommPort(AppConfig.ComPort);
            Monitor.Start();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UploadDataTick(object sender, EventArgs e)
        {
            List<MeterReading> meterReadings = new List<MeterReading>();

            // HACK
            Aggregator.Enable = AppConfig.PostEnable;

            while (Monitor.MeterReadings.Count > 0)
            {
                MonitorReading mr = Monitor.MeterReadings.Dequeue();

                MonitorToMeter map = AppConfig.Mappings.Find((mapping) => mapping.Monitor.Equals(mr.MeterID));

                if (map != null)
                {
                    string meter = map.Meter;
                    int power = Convert.ToInt32(mr.Power);
                    int time = DateTime.Parse(mr.Time).ToUnixTime();

                    meterReadings.Add(new MeterReading() { Meter = meter, Power = power, Time = time });
                }
            }

            if (meterReadings.Count > 0)
            {
                Aggregator.AddMeterReadings(meterReadings);
            }
        }
    }
}
